/**
* @brief 设备管理实现
* 实现设备数据的加载、保存、添加、删除、查找、更新等操作
*/
#include "device.h"




/**
* @brief 生成唯一设备ID
* 基于全局计数器自动生成不重复的设备ID
* @return int 新生成的设备ID
*/
int generate_id()
{
	return dev_id_min++;
}

/**
* @brief 显示设备的完整信息
* @param data 指向设备数据的指针
*/
void showfun_dev_full(const void *data)
{
	device_t *dev = (device_t *)data;
	printf("设备号:%d\n",dev->dev_id);
	printf("设备序号:%d\n",dev->dev_order);
	printf("设备工作状态:%c\n",dev->dev_status);
	printf("设备当前值:%f\n",dev->cur_value);
	printf("设备名:%s\n",dev->dev_name);
	printf("设备类型:%s\n",dev->dev_type);
	printf("设备IP:%s\n",dev->dev_ip);
	printf("额定功率:%f\n",dev->power_ele);
	printf("\n");
}

/**
* @brief 设备ID比较函数
* @param data1 设备1数据指针
* @param data2 设备2数据指针
* @return int 比较结果(>0, =0, <0)
*/
int cmpfun_dev_id(const void *data1, const void *data2)
{
	device_t *dev1 = (device_t *)data1;
	device_t *dev2 = (device_t *)data2;
	return dev1->dev_id - dev2->dev_id;
}

/**
 * @brief 设备名称比较函数
 * 
 * @param data1 设备1数据指针
 * @param data2 设备2数据指针
 * @return int 字符串比较结果
 */
int cmpfun_dev_name(const void *data1, const void *data2)
{
	device_t *dev1 = (device_t *)data1;
	device_t *dev2 = (device_t *)data2;
	return strcmp(dev1->dev_name,dev2->dev_name);
}

/**
 * @brief 设备类型比较函数
 * 
 * @param data1 设备1数据指针
 * @param data2 设备2数据指针
 * @return int 字符串比较结果
 */
int cmpfun_dev_type(const void *data1, const void *data2)
{
	device_t *dev1 = (device_t *)data1;
	device_t *dev2 = (device_t *)data2;
	return strcmp(dev1->dev_type,dev2->dev_type);
}


/**
 * @brief 更新设备名称
 * 
 * @param data1 待更新的设备数据指针
 * @param data2 包含新名称的设备数据指针
 * @return int 操作状态(0=成功)
 */
int updatefun_dev_name(void *data1, const void *data2)
{
	device_t *dev1 = (device_t *)data1;
	device_t *dev2 = (device_t *)data2;
	strcpy(dev1->dev_name,dev2->dev_name);
	return 0;

}


/**
 * @brief 更新设备类型
 * 
 * @param data1 待更新的设备数据指针
 * @param data2 包含新类型的设备数据指针
 * @return int 操作状态(0=成功)
 */
int updatefun_dev_type(void *data1, const void *data2)
{
	device_t *dev1 = (device_t *)data1;
	device_t *dev2 = (device_t *)data2;
	strcpy(dev1->dev_type,dev2->dev_type);
	return 0;
}

/**
 * @brief 更新设备IP地址
 * 
 * @param data1 待更新的设备数据指针
 * @param data2 包含新IP的设备数据指针
 * @return int 操作状态(0=成功)
 */
int updatefun_dev_ip(void *data1, const void *data2)
{
	device_t *dev1 = (device_t *)data1;
	device_t *dev2 = (device_t *)data2;
	strcpy(dev1->dev_ip, dev2->dev_ip);
	return 0;
}


/**
 * @brief 从文件加载设备数据到链表
 * 
 * @return node_t* 设备链表头指针(失败返回NULL)
 */
node_t *load_dev()
{
	// 尝试打开设备数据文件
	FILE *fp = fopen(DEV_FILE, "r");
	if (fp == NULL) {
		return create_dlist();// 文件不存在时创建空链表 
	}
	// 创建链表头节点
	node_t *head = create_dlist();
	SYSERR(NULL,==,head,"create dlist error",NULL);
	// 读取最大ID和设备数量
	int max_id, count;
	fscanf(fp, "%d %d", &max_id, &count);
	// 更新全局ID最小值（确保新ID不重复）
	if (max_id >= dev_id_min)
		dev_id_min = max_id + 1; 
	// 逐个读取设备数据
	for (int i = 0; i < count; i++) {
		device_t *dev = malloc(sizeof(device_t));
		// 格式化读取设备信息
		fscanf(fp, "%d %d %c %f %31s %31s %15s %f", 
				&dev->dev_id, &dev->dev_order, &dev->dev_status, &dev->cur_value,
				dev->dev_name, dev->dev_type, dev->dev_ip, &dev->power_ele);
		// 插入链表尾部
		insert_tdlist(head, dev, sizeof(device_t));
		free(dev);// 释放临时结构体
	}
	fclose(fp);
	return head;
}


/**
 * @brief 将设备链表保存到文件
 * 
 * @param head 链表头指针
 * @return int 操作状态(0=成功, -1=失败)
 */
int save_dev(node_t *head)
{
	SYSERR(NULL,==,head,"head is null",-1);
	FILE *fp = fopen(DEV_FILE, "w");
	SYSERR(NULL,==,fp,"open file error",-1);
	// 统计设备数量和最大ID
	int count = 0;
	int max_id = 0;
	node_t *cur = head->after;
	while (cur != head) 
	{
		device_t *dev = (device_t *)cur->data;
		count++;
		if (dev->dev_id > max_id) 
		{
			max_id = dev->dev_id;
		}
		cur = cur->after;
	}
	// 写入头部信息（最大ID和设备总数）
	fprintf(fp,"%d %d\n",max_id,count);
	// 遍历链表写入设备数据
	cur = head->after;
	while (cur != head)
	{
		device_t *dev = (device_t *)cur->data;
		fprintf(fp, "%d %d %c %.f %s %s %s %.f\n", dev->dev_id, dev->dev_order, dev->dev_status, dev->cur_value,
				dev->dev_name, dev->dev_type, dev->dev_ip, dev->power_ele);
		cur = cur->after;
	}
	fclose(fp);
	return 0;
}


/**
 * @brief 重新设置设备序号
 * 基于链表顺序重新编号设备序号
 * 
 * @param head 链表头指针
 * @return int 操作状态(0=成功, -1=失败)
 */
int set_device_order(node_t *head)
{
	SYSERR(NULL,==,head,"head is null",-1);
	int order = 1;
	node_t *cur = head->after;
	while (cur != head) {
		device_t *dev = (device_t *)cur->data;
		dev->dev_order = order++;// 顺序编号
		cur = cur->after;
	}
	return 0;
}


/**
 * @brief 添加新设备到链表
 * 
 * @param head 链表头指针
 * @param newdev 新设备数据指针
 * @return int 操作状态(0=成功, -1=失败)
 */
int add_dev(node_t *head, const device_t *newdev)
{
	SYSERR(NULL,==,head,"head is null",-1);
	SYSERR(NULL,==,newdev,"newdev is null",-1);
	// 插入链表尾部
	int res = insert_tdlist(head,newdev,sizeof(device_t));
	if(res == 0)
		return 0;
	return -1;
}


/**
 * @brief 查找设备
 * 
 * @param head 链表头指针
 * @param mode 查找模式(1=ID,2=名称,3=类型)
 * @param cmpdev 包含查找条件的设备指针
 * @return node_t* 查找到的节点/链表(失败返回NULL)
 */
node_t *find_dev(node_t *head,int mode,const device_t *cmpdev)
{
	SYSERR(NULL,==,head,"head is null",NULL);
	SYSERR(NULL,==,cmpdev,"cmpdev is null",NULL);
	node_t *temp = create_dlist();
	int flag;// 找到标志
	if(temp == NULL)
		return NULL;
	switch(mode)
	{
		// 模式1：按ID精确查找（返回单个节点）
	case 1:
		return find_vdlist(head,cmpdev,cmpfun_dev_id);
		// 模式2：按名称查找（返回链表）
	case 2:
		{
			node_t *cur = head->after;
			flag = 0;
			while(cur != head)
			{
				if(cmpfun_dev_name(cur->data,cmpdev) == 0)
				{
					insert_tdlist(temp,cur->data,sizeof(device_t));
					flag = 1;
				}
				cur = cur->after;
			}
			if(flag == 0)
				return NULL;
			return temp;
		}
		// 模式3：按类型查找（返回链表）
	case 3:
		{				
			node_t *cur = head->after;// 创建临时链表存储结果
			flag = 0;
			while(cur != head)
			{
				if(cmpfun_dev_type(cur->data,cmpdev) == 0)
				{
					insert_tdlist(temp,cur->data,sizeof(device_t));
					flag = 1;
				}
				cur = cur->after;
			}
			if(flag == 0)
			{
				destroy_dlist(&temp); // 未找到时清理临时链表
				return NULL;
			}
			return temp;
		}
	default :
		return NULL;
		break;
	}

}


/**
 * @brief 删除设备
 * 
 * @param head 链表头指针
 * @param mode 删除模式(1=ID,2=名称,3=类型)
 * @param dev 包含删除条件的设备指针
 * @return int 操作状态(0=成功, -1=失败)
 */
int del_dev(node_t *head,int mode,const device_t *dev)
{
	SYSERR(NULL,==,head,"head is NULL",-1);
	SYSERR(NULL,==,dev,"dev is NULL",-1);
	SYSERR(head->after,==,head,"devlist is empty",-1);
	int flag = 0;// 删除成功标志
	switch(mode)
	{
		// 模式1：按ID删除（精确删除单个设备）
	case 1:
		if(!(delete_vdlist(head,(void *)dev,cmpfun_dev_id)))
			return 0;
		// 模式2：按名称删除（删除所有同名设备）
	case 2:
		{
			node_t *cur = head->after;// 保存下一个节点指针
			while(cur != head)
			{
				node_t *next = cur->after;
				if(cmpfun_dev_name(cur->data,dev) == 0)
				{
					delete_vdlist(head,(void *)dev,cmpfun_dev_name);// 删除当前节点
					flag = 1;
				}
				cur = next;
			}	
			// 根据删除结果返回
			if(flag)
				return 0;
			return -1;
		}
		// 模式3：按类型删除（删除所有同类型设备）
	case 3:
		{
			node_t *cur = head->after;
			while(cur != head)
			{
				node_t *next = cur->after;
				if(cmpfun_dev_type(cur->data,dev) == 0)
				{
					delete_vdlist(head,(void *)dev,cmpfun_dev_type);
					flag = 1;
				}
				cur = next;
			}
			if(flag)
				return 0;
			return -1;
		}
	default:
		return -1;
	}
	return 0;
}


/**
 * @brief 更新设备属性
 * 
 * @param head 链表头指针
 * @param id 要更新的设备ID
 * @param updatefun 更新函数指针
 * @param updatedev 包含更新数据的设备指针
 * @return node_t* 更新后的节点指针(失败返回NULL)
 */
node_t *update_dev(node_t *head,int id,updatefun_t updatefun,const device_t *updatedev)
{
	SYSERR(NULL,==,head,"head is NULL",NULL);
	SYSERR(NULL,==,updatedev,"updatedev is NULL",NULL);
	SYSERR(head->after,==,head,"devlist is empty",NULL);
	device_t *olddev = malloc(sizeof(device_t));// 创建临时设备用于查找
	olddev->dev_id = id;
	// 按ID查找设备
	node_t *temp = find_dev(head,1,olddev);
	free(olddev);
	if(temp == NULL)
		return NULL;
	// 执行更新操作
	updatefun(temp->data,updatedev);
	return temp;
}


/**
 * @brief 设备链表排序
 * 
 * @param head 链表头指针
 * @param cmpfun 比较函数指针
 * @return int 操作状态(0=成功, -1=失败)
 */
int sort_dev(node_t *head, cmpfun_t cmpfun)
{
	if(NULL == head || head->after == head)
		return -1;
	node_t *inode = NULL,*jnode = NULL,*end = NULL;
	void *temp = NULL;
	int flag;// 交换标志
	// 外层循环控制排序轮次
	for(inode = head->after,end = head->before;inode != head;inode = inode->after,end = end->before)
	{
		flag = 0;
		// 内层循环进行相邻比较
		for(jnode = head->after;jnode != end;jnode = jnode->after)
		{
			if((cmpfun(jnode->data,jnode->after->data))>0)
			{
				// 交换节点数据
				temp = jnode->data;
				jnode->data = jnode->after->data;
				jnode->after->data = temp;
				flag = 1;// 标记发生交换
			}
		}
		if(!flag)
			break;// 本轮无交换说明已有序
	}
	return 0;
}


/**
 * @brief 显示单个设备信息
 * 
 * @param temp 设备节点指针
 * @param showfun 显示函数指针
 */
void show_dev(node_t *temp, showfun_t showfun)
{
	SYSERR(NULL,==,temp,"temp is NULL",);
	showfun(temp->data);
}

